﻿using System.Buffers;
using System.Buffers.Binary;
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
using System.Text;

namespace FlyingEye
{
    public static class CompositeKeyGenerator
    {
        // 内存池复用缓冲区（避免GC）
        private static readonly ArrayPool<byte> _bufferPool = ArrayPool<byte>.Shared;

        /// <summary>
        /// 生成全局唯一键（40字符固定长度）
        /// </summary>
        public static string GenerateKey(params object[] values)
        {
            // 预计算所需缓冲区大小
            int totalBytes = CalculateTotalBytes(values);
            byte[] buffer = _bufferPool.Rent(totalBytes);
            try
            {
                Span<byte> span = buffer.AsSpan();
                int offset = 0;

                foreach (var value in values)
                {
                    switch (value)
                    {
                        // 基本数值类型
                        case bool b:
                            WriteTypeMarker(ref span, ref offset, 0x01);
                            span[offset++] = (byte)(b ? 1 : 0);
                            break;
                        case sbyte sb:
                            WriteTypeMarker(ref span, ref offset, 0x02);
                            span[offset++] = (byte)sb;
                            break;
                        case byte bVal:
                            WriteTypeMarker(ref span, ref offset, 0x03);
                            span[offset++] = bVal;
                            break;
                        case short s:
                            WriteTypeMarker(ref span, ref offset, 0x04);
                            BinaryPrimitives.WriteInt16LittleEndian(span[offset..], s);
                            offset += sizeof(short);
                            break;
                        case ushort us:
                            WriteTypeMarker(ref span, ref offset, 0x05);
                            BinaryPrimitives.WriteUInt16LittleEndian(span[offset..], us);
                            offset += sizeof(ushort);
                            break;
                        case int i:
                            WriteTypeMarker(ref span, ref offset, 0x06);
                            BinaryPrimitives.WriteInt32LittleEndian(span[offset..], i);
                            offset += sizeof(int);
                            break;
                        case uint ui:
                            WriteTypeMarker(ref span, ref offset, 0x07);
                            BinaryPrimitives.WriteUInt32LittleEndian(span[offset..], ui);
                            offset += sizeof(uint);
                            break;
                        case long l:
                            WriteTypeMarker(ref span, ref offset, 0x08);
                            BinaryPrimitives.WriteInt64LittleEndian(span[offset..], l);
                            offset += sizeof(long);
                            break;
                        case ulong ul:
                            WriteTypeMarker(ref span, ref offset, 0x09);
                            BinaryPrimitives.WriteUInt64LittleEndian(span[offset..], ul);
                            offset += sizeof(ulong);
                            break;

                        // 浮点类型（网页1的二进制编码方案）
                        case float f:
                            WriteTypeMarker(ref span, ref offset, 0x0A);
                            BinaryPrimitives.WriteSingleLittleEndian(span[offset..], f);
                            offset += sizeof(float);
                            break;
                        case double d:
                            WriteTypeMarker(ref span, ref offset, 0x0B);
                            BinaryPrimitives.WriteDoubleLittleEndian(span[offset..], d);
                            offset += sizeof(double);
                            break;
                        case decimal dec:
                            WriteTypeMarker(ref span, ref offset, 0x0C);
                            EncodeDecimal(ref span, ref offset, dec);
                            break;

                        // 字符与字符串（网页3的UTF-16编码）
                        case char c:
                            WriteTypeMarker(ref span, ref offset, 0x0D);
                            BinaryPrimitives.WriteUInt16LittleEndian(span[offset..], c);
                            offset += sizeof(char);
                            break;
                        case string s:
                            WriteTypeMarker(ref span, ref offset, 0x0E);
                            EncodeString(ref span, ref offset, s);
                            break;

                        // 日期与Guid
                        case DateTime dt:
                            WriteTypeMarker(ref span, ref offset, 0x0F);
                            BinaryPrimitives.WriteInt64LittleEndian(span[offset..], dt.Ticks);
                            offset += sizeof(long);
                            break;
                        case Guid guid:
                            WriteTypeMarker(ref span, ref offset, 0x10);
                            guid.TryWriteBytes(span[offset..]);
                            offset += 16;
                            break;

                        // 枚举类型（转为底层整型）
                        case Enum e:
                            WriteTypeMarker(ref span, ref offset, 0x11);
                            var underlyingType = Enum.GetUnderlyingType(e.GetType());
                            long enumValue = Convert.ToInt64(Convert.ChangeType(e, underlyingType));
                            BinaryPrimitives.WriteInt64LittleEndian(span[offset..], enumValue);
                            offset += sizeof(long);
                            break;
                        default:
                            throw new NotSupportedException($"Unsupported type: {value.GetType().FullName}");
                    }
                }

                // 混合哈希算法（xxHash128 + CRC32）
                return ComputeHybridHash(span[..offset]);
            }
            finally
            {
                _bufferPool.Return(buffer);
            }
        }

        // 补充类型编码方法
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static void WriteTypeMarker(ref Span<byte> span, ref int offset, byte marker)
        {
            span[offset++] = marker;
        }

        private static void EncodeDecimal(ref Span<byte> span, ref int offset, decimal value)
        {
            Span<int> bits = stackalloc int[4];
            decimal.GetBits(value, bits);

            foreach (var part in bits)
            {
                BinaryPrimitives.WriteInt32LittleEndian(span[offset..], part);
                offset += sizeof(int);
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static void EncodeString(ref Span<byte> span, ref int offset, string s)
        {
            int maxBytes = Encoding.UTF8.GetMaxByteCount(s.Length);
            if (offset + sizeof(int) + maxBytes > span.Length)
                throw new OverflowException();

            int byteCount = Encoding.UTF8.GetBytes(s, span[(offset + sizeof(int))..]);
            BinaryPrimitives.WriteInt32LittleEndian(span[offset..], byteCount);
            offset += sizeof(int) + byteCount;
        }

        private static string ComputeHybridHash(Span<byte> data)
        {
            // 第一层哈希：xxHash128（极速）
            var hash128 = System.IO.Hashing.XxHash128.HashToUInt128(data);

            // 第二层校验：CRC32（零冲突保障）
            uint crc32 = System.IO.Hashing.Crc32.HashToUInt32(data);

            // 组合成40字符唯一键
            return $"{hash128:X32}|{crc32:X8}"; // 使用非十六进制字符分隔
        }

        private static readonly ConcurrentDictionary<int, int> _maxByteCache = new();

        private static int GetCachedMaxByteCount(string s) =>
            _maxByteCache.GetOrAdd(s.Length, len => Encoding.UTF8.GetMaxByteCount(len));

        // 更新字节计算逻辑
        private static int CalculateTotalBytes(object[] values)
        {
            int total = 0;
            foreach (var value in values)
            {
                total += value switch
                {
                    bool => 1 + 1,        // 类型标记(1) + 数据(1)
                    sbyte => 1 + 1,
                    byte => 1 + 1,
                    short => 1 + 2,
                    ushort => 1 + 2,
                    int => 1 + 4,
                    uint => 1 + 4,
                    long => 1 + 8,
                    ulong => 1 + 8,
                    float => 1 + 4,
                    double => 1 + 8,
                    decimal => 1 + 16,    // 4个int * 4字节
                    char => 1 + 2,        // UTF-16编码
                    string s => 1 + sizeof(int) + GetCachedMaxByteCount(s),
                    DateTime => 1 + 8,
                    Guid => 1 + 16,
                    Enum => 1 + 8,
                    _ => throw new NotSupportedException()
                };
            }
            return total;
        }
    }

}
